package com.education.ai.dao.impl;

import com.education.ai.dao.StudentDao;
import com.education.ai.entity.Student;
import com.education.ai.util.JdbcUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 学生数据访问实现类
 */
@Repository
public class StudentDaoImpl implements StudentDao {

    private static final Logger logger = LoggerFactory.getLogger(StudentDaoImpl.class);
    
    @Autowired
    private JdbcUtil jdbcUtil;
    
    @Override
    public List<Student> findAll() {
        String sql = "SELECT * FROM students";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql));
    }
    
    @Override
    public Optional<Student> findById(Long id) {
        String sql = "SELECT * FROM students WHERE id = ?";
        List<Map<String, Object>> results = jdbcUtil.executeQuery(sql, id);
        return results.isEmpty() ? Optional.empty() : Optional.of(mapRowToStudent(results.get(0)));
    }
    
    @Override
    public Optional<Student> findByStudentId(String studentId) {
        String sql = "SELECT * FROM students WHERE student_id = ?";
        List<Map<String, Object>> results = jdbcUtil.executeQuery(sql, studentId);
        return results.isEmpty() ? Optional.empty() : Optional.of(mapRowToStudent(results.get(0)));
    }
    
    @Override
    public List<Student> findByClassId(String classId) {
        String sql = "SELECT * FROM students WHERE class_id = ?";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql, classId));
    }
    
    @Override
    public List<Student> findByGrade(String grade) {
        String sql = "SELECT * FROM students WHERE grade = ?";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql, grade));
    }
    
    @Override
    public List<Student> findByNameContaining(String namePart) {
        String sql = "SELECT * FROM students WHERE name LIKE ?";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql, "%" + namePart + "%"));
    }
    
    @Override
    public List<Student> findByClassIdAndGrade(String classId, String grade) {
        String sql = "SELECT * FROM students WHERE class_id = ? AND grade = ?";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql, classId, grade));
    }
    
    @Override
    public List<Student> findByClassName(String className) {
        String sql = "SELECT * FROM students WHERE class_name = ?";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql, className));
    }
    
    @Override
    public List<Student> findWithPagination(int offset, int limit) {
        String sql = "SELECT * FROM students LIMIT ? OFFSET ?";
        return mapResultsToStudents(jdbcUtil.executeQuery(sql, limit, offset));
    }
    
    @Override
    public Student save(Student student) {
        if (student.getId() == null) {
            // 插入操作
            String sql = "INSERT INTO students (name, student_id, grade, class_id, class_name, profile, create_time, update_time, password, phone, email, status, last_login_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            // 设置创建和更新时间
            LocalDateTime now = LocalDateTime.now();
            if (student.getCreateTime() == null) {
                student.setCreateTime(now);
            }
            if (student.getUpdateTime() == null) {
                student.setUpdateTime(now);
            }
            
            // 检查studentId是否为null，如果为null则生成一个默认学号
            if (student.getStudentId() == null || student.getStudentId().trim().isEmpty()) {
                // 生成基于时间的学号，格式：年份后两位 + 月份 + 日 + 5位随机数
                String year = String.valueOf(LocalDateTime.now().getYear()).substring(2);
                String month = String.format("%02d", LocalDateTime.now().getMonthValue());
                String day = String.format("%02d", LocalDateTime.now().getDayOfMonth());
                String random = String.format("%05d", (int)(Math.random() * 100000));
                student.setStudentId(year + month + day + random);
                
                logger.info("为新学生生成学号: {}", student.getStudentId());
            }
            
            long id = jdbcUtil.executeInsert(sql, 
                    student.getName(), 
                    student.getStudentId(), 
                    student.getGrade(), 
                    student.getClassId(), 
                    student.getClassName(), 
                    student.getProfile(),
                    student.getCreateTime(),
                    student.getUpdateTime(),
                    student.getPassword(),
                    student.getPhone(),
                    student.getEmail(),
                    student.getStatus(),
                    student.getLastLoginTime());
            
            student.setId(id);
            return student;
        } else {
            // 更新操作
            updateInternally(student);
            return student;
        }
    }
    
    /**
     * 内部更新方法，用于save方法调用
     */
    private boolean updateInternally(Student student) {
        String sql = "UPDATE students SET name = ?, grade = ?, class_id = ?, class_name = ?, profile = ?, update_time = ?, password = ?, phone = ?, email = ?, status = ?, last_login_time = ? WHERE id = ?";
        
        // 设置更新时间
        student.setUpdateTime(LocalDateTime.now());
        
        int rows = jdbcUtil.executeUpdate(sql,
                student.getName(),
                student.getGrade(),
                student.getClassId(),
                student.getClassName(),
                student.getProfile(),
                student.getUpdateTime(),
                student.getPassword(),
                student.getPhone(),
                student.getEmail(),
                student.getStatus(),
                student.getLastLoginTime(),
                student.getId());
        
        return rows > 0;
    }
    
    @Override
    public void update(Student student) {
        String sql = "UPDATE students SET name = ?, grade = ?, class_id = ?, class_name = ?, profile = ?, update_time = ?, password = ?, phone = ?, email = ?, status = ?, last_login_time = ? WHERE id = ?";
        
        // 设置更新时间
        student.setUpdateTime(LocalDateTime.now());
        
        jdbcUtil.executeUpdate(sql,
                student.getName(),
                student.getGrade(),
                student.getClassId(),
                student.getClassName(),
                student.getProfile(),
                student.getUpdateTime(),
                student.getPassword(),
                student.getPhone(),
                student.getEmail(),
                student.getStatus(),
                student.getLastLoginTime(),
                student.getId());
    }
    
    @Override
    public void delete(Long id) {
        String sql = "DELETE FROM students WHERE id = ?";
        jdbcUtil.executeUpdate(sql, id);
    }
    
    /**
     * 根据学生ID删除学生
     * @deprecated 使用 delete(Long id) 代替
     */
    @Deprecated
    public boolean deleteById(Long id) {
        String sql = "DELETE FROM students WHERE id = ?";
        int rows = jdbcUtil.executeUpdate(sql, id);
        return rows > 0;
    }
    
    /**
     * 根据学号删除学生
     * 注意：这不是StudentDao接口要求的方法，但保留为内部使用
     */
    public boolean deleteByStudentId(String studentId) {
        String sql = "DELETE FROM students WHERE student_id = ?";
        int rows = jdbcUtil.executeUpdate(sql, studentId);
        return rows > 0;
    }
    
    @Override
    public long count() {
        String sql = "SELECT COUNT(*) AS count FROM students";
        List<Map<String, Object>> results = jdbcUtil.executeQuery(sql);
        if (!results.isEmpty()) {
            return ((Number) results.get(0).get("count")).longValue();
        }
        return 0;
    }
    
    /**
     * 将查询结果映射为学生对象列表
     */
    private List<Student> mapResultsToStudents(List<Map<String, Object>> results) {
        List<Student> students = new ArrayList<>();
        for (Map<String, Object> row : results) {
            students.add(mapRowToStudent(row));
        }
        return students;
    }
    
    /**
     * 将单行结果映射为学生对象
     */
    private Student mapRowToStudent(Map<String, Object> row) {
        Student student = new Student();
        student.setId(((Number) row.get("id")).longValue());
        student.setName((String) row.get("name"));
        student.setStudentId((String) row.get("student_id"));
        student.setGrade((String) row.get("grade"));
        student.setClassId((String) row.get("class_id"));
        student.setClassName((String) row.get("class_name"));
        student.setProfile((String) row.get("profile"));
        student.setPassword((String) row.get("password"));
        student.setPhone((String) row.get("phone"));
        student.setEmail((String) row.get("email"));
        
        // 处理状态字段
        Object statusObj = row.get("status");
        if (statusObj != null) {
            if (statusObj instanceof Number) {
                student.setStatus(((Number) statusObj).intValue());
            } else {
                student.setStatus(Integer.parseInt(statusObj.toString()));
            }
        }
        
        // 处理日期时间字段，转换为LocalDateTime
        if (row.get("create_time") != null) {
            Object timeObj = row.get("create_time");
            student.setCreateTime(convertToLocalDateTime(timeObj));
        }
        
        if (row.get("update_time") != null) {
            Object timeObj = row.get("update_time");
            student.setUpdateTime(convertToLocalDateTime(timeObj));
        }
        
        if (row.get("last_login_time") != null) {
            Object timeObj = row.get("last_login_time");
            student.setLastLoginTime(convertToLocalDateTime(timeObj));
        }
        
        return student;
    }
    
    /**
     * 转换各种日期类型为LocalDateTime
     */
    private LocalDateTime convertToLocalDateTime(Object timeObj) {
        if (timeObj instanceof Date) {
            return Instant.ofEpochMilli(((Date) timeObj).getTime())
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
        } else if (timeObj instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) timeObj).toLocalDateTime();
        } else if (timeObj instanceof java.sql.Date) {
            return Instant.ofEpochMilli(((java.sql.Date) timeObj).getTime())
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
        } else if (timeObj instanceof LocalDateTime) {
            return (LocalDateTime) timeObj;
        } else {
            logger.warn("无法识别的时间类型: {}, 值: {}", 
                    timeObj != null ? timeObj.getClass().getName() : "null", 
                    timeObj);
            return null;
        }
    }
} 